package com.ug.system.controller.tencent;

import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ug.common.cache.redis.RedisCacheService;
import com.ug.common.constant.CommonConstants;
import com.ug.config.tencent.QQConfig;
import com.ug.system.entity.SysUser;
import com.ug.system.service.SysUserService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author LY
 * @create 2024/8/26 13:48
 * @Description 腾讯应用回调接口 地址：https://wiki.connect.qq.com/%e4%bd%bf%e7%94%a8authorization_code%e8%8e%b7%e5%8f%96access_token
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/tencent")
public class CallbackController {

    private static final Logger logger = LoggerFactory.getLogger(CallbackController.class);

    private final QQConfig qqConfig;
    private final RedisCacheService redisCacheService;
    private final SysUserService sysUserService;

    /**
     * qq登录回调
     */
    @GetMapping("/qqCallback")
    public String getCallBackInfo(HttpServletRequest request){
        logger.info("QQ登录回调入参：{}", request.getQueryString());
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        //  判断初始获取code时携带的uuid标识
        String stateCache = redisCacheService.getString(state);
        if (StrUtil.isEmpty(stateCache)){
            throw new RuntimeException("QQ,state错误");
        }
        //  返回参数格式：access_token=&expires_in=&openid=&refresh_token= 需要截取获取对应数据
        String info = accessToken(code);
        logger.info("access token info:{}", info);
        //  access token
        String accessToken = StrUtil.subBetween(info, "access_token=", "&");
        //  获取用户openid
        String openId = StrUtil.subBetween(info, "openid=", "&");
        //  获取用户信息
        String userInfo = getUserInfo(accessToken, openId);
        JSONObject jsonObject = JSONObject.parseObject(userInfo);
        logger.info("QQ用户信息:{}", jsonObject);
        //  获取用户昵称
        String nickname = jsonObject.getString("nickname");
        SysUser sysUser = new SysUser();
        sysUser.setNickName(nickname);
        sysUser.setOpenId(openId);
        sysUser.setRegisterType(CommonConstants.LOGIN_TYPE_QQ);
        //  第一次快捷登录时保存用户信息
        sysUserService.saveUserByFirst(sysUser);
        //  缓存回调获得的openId登录的时候取出进行登录
        redisCacheService.put(state, openId, 60 * 5);
        //  前端页面弹窗关闭
        return CommonConstants.WINDOW_CLOSED;
    }

    /**
     * 获取access token和openid
     */
    public String accessToken(String code){
        // accessToken地址
        String accessTokenURL = qqConfig.getAccessTokenUrl();
        // 回调地址 ,进行Encode转码
        String redirectUri = qqConfig.getRedirectUrl();
        // 拼接参数
        String params = accessTokenURL +
                "?grant_type=authorization_code" +
                "&client_id=" + qqConfig.getAppId() +
                "&client_secret=" + qqConfig.getAppKey() +
                "&code=" + code +
                "&redirect_uri=" + URLEncodeUtil.encodeFragment(redirectUri) +
                "&need_openid=1";
        return HttpUtil.get(params);
    }

    /**
     * 获取用户信息
     */
    public String getUserInfo(String accessToken, String openId){
        // 拼接参数
        String params = qqConfig.getUserInfoUrl() +
                "?access_token=" + accessToken +
                "&oauth_consumer_key=" + qqConfig.getAppId() +
                "&openid=" + openId;
        return HttpUtil.get(params);
    }
}
